﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace mlnx_os_sysdump_analyzer
{
    class Processes : IDisposable
    {
        private long totalVirtualMemoryInUse = 0;
        private long totalRealMemoryInUse = 0;
        private DataTable processesListTable = null;
        private string outputOfFree = "";
        public bool isHttpdRunning = false;
        private bool KEEP_RUNNING; 
        private string OUTPUT_DIR_PATH;
        //
        //----------------------------------------------------
        //
        public Processes(ref bool KEEP_RUNNING, ref string OUTPUT_DIR_PATH)
        {
            this.KEEP_RUNNING = KEEP_RUNNING;   
            this.OUTPUT_DIR_PATH = OUTPUT_DIR_PATH;

            // create a DataTable
            processesListTable = new DataTable();
            // add columns
            processesListTable.Columns.Add("USER", typeof(string));
            processesListTable.Columns.Add("PID", typeof(int));
            processesListTable.Columns.Add("LWP", typeof(int));
            processesListTable.Columns.Add("PPID", typeof(int));
            processesListTable.Columns.Add("NLWP", typeof(int));
            processesListTable.Columns.Add("CPU", typeof(double));
            processesListTable.Columns.Add("PRI", typeof(int));
            processesListTable.Columns.Add("NI", typeof(string));
            processesListTable.Columns.Add("VSZ", typeof(long));
            processesListTable.Columns.Add("RSS", typeof(long));
            processesListTable.Columns.Add("TT", typeof(string));
            processesListTable.Columns.Add("STAT", typeof(string));
            processesListTable.Columns.Add("WCHAN", typeof(string));
            processesListTable.Columns.Add("STARTED", typeof(string));
            processesListTable.Columns.Add("TIME", typeof(string));
            processesListTable.Columns.Add("COMMAND", typeof(string));
        }
        //
        //----------------------------------------------------
        //
        public long getTotalVirtualMemoryInUse()
        {
            return totalVirtualMemoryInUse;
        }
        //
        //----------------------------------------------------
        //
        public long getTotalRealMemoryInUse()
        {
            return totalRealMemoryInUse;
        }
        //
        //----------------------------------------------------
        //
        public string getOutputOfFree()
        {
            return outputOfFree;
        }
        //
        //----------------------------------------------------
        //
        public DataTable getProcessesList()
        {
            return processesListTable;
        }
        //
        //----------------------------------------------------
        //
        public void scanProcessesInfoNewThread()
        {
            string path = Methods.FindFileRec(OUTPUT_DIR_PATH, "sysinfo.txt");
            if (path != null)
            {
                scanProcessesInfo(path);
            }
        }
        //
        //----------------------------------------------------
        //
        public void scanProcessesInfo(string srcFilePath)
        {
            if (srcFilePath == null)
                return;
            StreamReader sr = new StreamReader(srcFilePath);
            string line = "";
            try
            {
                // #################################################
                // get Output of 'free':
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    if (sr.ReadLine().Contains("Output of 'free':"))
                    {
                        break;
                    }
                }
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    line = sr.ReadLine();
                    if (line.Contains("============="))
                    {
                        break;
                    }
                    else
                    {
                        outputOfFree += line + "\r\n";
                    }
                }

                // #################################################
                // get Output of 'ps
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    if (sr.ReadLine().Contains("Output of 'ps"))
                    {
                        break;
                    }
                }
                sr.ReadLine(); sr.ReadLine();
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    // read line
                    line = sr.ReadLine();
                    try
                    {
                        if (line.Contains("============="))
                        {
                            sr.Dispose();
                            return;
                        }
                        // remove the extra white spaces
                        // Note: from index=15 (16-th column) and on = COMMAND
                        line = Methods.RemoveExtraSpaces(line);
                        if (!line.Equals(""))
                        {
	                        string []arr = Regex.Split(line, " ");
	                        ProcessesFields pf = new ProcessesFields();
	                        pf.USER = arr[0];                        
	                        pf.PID = Int32.Parse(arr[1]);
	                        pf.LWP = Int32.Parse(arr[2]);
	                        pf.PPID = Int32.Parse(arr[3]);
	                        pf.NLWP = Int32.Parse(arr[4]);
	                        pf.CPU = double.Parse(arr[5]);
	                        pf.PRI = Int32.Parse(arr[6]);
	                        pf.NI = arr[7];
	                        pf.VSZ = long.Parse(arr[8]);
	                        totalVirtualMemoryInUse += pf.VSZ; // update total virtual memory in user
	                        pf.RSS = long.Parse(arr[9]); 
	                        totalRealMemoryInUse += pf.RSS; // update total real memory in user
	                        pf.TT = arr[10];
	                        pf.STAT = arr[11];
	                        pf.WCHAN = arr[12];
	                        pf.STARTED = arr[13];
                            int startIndex = 15;
                            if (pf.STARTED.Contains(":"))
                            {
                                pf.TIME = arr[14];
                                startIndex = 15;
                            }
                            else
                            {
                                pf.STARTED += " " + arr[14];
                                pf.TIME = arr[15];
                                startIndex = 16;
                            }

                            for (int i = startIndex; i < arr.Length; i++)
	                        {
	                            pf.COMMAND += arr[i] + " ";
	                        }
	                        processesListTable.Rows.Add(pf.USER,
	                            pf.PID,
	                            pf.LWP,
	                            pf.PPID,
	                            pf.NLWP,
	                            pf.CPU,
	                            pf.PRI,
	                            pf.NI,
	                            pf.VSZ,
	                            pf.RSS,
	                            pf.TT,
	                            pf.STAT,
	                            pf.WCHAN,
	                            pf.STARTED,
	                            pf.TIME,
	                            pf.COMMAND);
	
	                        if (pf.COMMAND.Contains("httpd"))
	                        {
	                            isHttpdRunning = true;
	                        }
                        }
                    }//try
                    catch { }
                }
                // #################################################
            }//try
            catch { }
            sr.Dispose();
        }
        //
        //----------------------------------------------------
        //

        public void Dispose()
        {
            if (processesListTable != null)
            {
                processesListTable.Dispose();
            }
        }
    }
}
